#############################################################################
#  Copyright (C) 2007 Boscovich, Maximiliano - mboscovich@gmail.com          #
#                                                                            #
#  This program is free software; you can redistribute it and/or modify      #
#  it under the terms of the GNU General Public License as published by      #
#  the Free Software Foundation; either version 3 of the License, or         #
#  (at your option) any later version. See tht GPL_Licence.txt for details.  #
#                                                                            #
#  This program is distributed in the hope that it will be useful,           #
#  but WITHOUT ANY WARRANTY; without even the implied warranty of            #
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              #
#  GNU General Public License for more details.                              #
#                                                                            #
##############################################################################

import sys
sys.path.append("../")

from sqlobject import dberrors
from formencode import Invalid

from view.Host_view import *
from model.tables import *
from model.packages import *
from model.configuration import *
import logModule


class Host_controller(Ui_Host_view):

    def __init__(self,host=None):
        self.widget = QtGui.QDialog()
        self.setupUi(self.widget)
        self.Refresh_Architectures()
        self.Refresh_Distributions()
        self.Refresh_Offices()
        self.Refresh_Templates()
        #############################################################
        # Connections
        self.widget.connect(self.pushButtonCancel, QtCore.SIGNAL("clicked()"),                               QtCore.SLOT('close()'))
        self.widget.connect(self.pushButtonOk, QtCore.SIGNAL("clicked()"),
                            self.add_or_edit_host)
        self.widget.connect(self.tabWidgetAddHost, 
                            QtCore.SIGNAL("currentChanged(int)"), 
                            self.Tab_change)
        self.widget.connect(self.pushButtonMustBeAdd, 
                            QtCore.SIGNAL("clicked()"), self.MustBeAdd)
        self.widget.connect(self.pushButtonMayNotBeAdd,
                            QtCore.SIGNAL("clicked()"),self.MayNotBeAdd)
        self.widget.connect(self.pushButtonMayBeAdd, 
                            QtCore.SIGNAL("clicked()"), self.MayBeAdd)
        self.widget.connect(self.pushButtonMustBeRemove, 
                            QtCore.SIGNAL("clicked()"),
                            self.MustBeRemove)
        self.widget.connect(self.pushButtonMayNotBeRemove, 
                            QtCore.SIGNAL("clicked()"), self.MayNotBeRemove)
        self.widget.connect(self.pushButtonMayBeRemove, 
                            QtCore.SIGNAL("clicked()"),self.MayBeRemove)
        self.widget.connect(self.comboBoxTemplate,
                            QtCore.SIGNAL("currentIndexChanged(int)"),
                            self.loadwidgetFromTemplate)
        self.lineEditHostname.setEnabled(True)
        self.pushButtonOk.setText("Agregar")
        #############################################################
                        
        if host <> None:
            self.editMode=True
            self.edit_view(host)
        else:
            self.editMode=False
    
    def add_or_edit_host(self):
        if self.editMode:
            self.edit_host()
        else:
            self.add_host()
   
    def edit_host(self):
        hostname = str(self.lineEditHostname.text())
        mac = str(self.lineEditMac.text())
        office = Office.selectBy(Name=str(self.comboBoxOffice.currentText()))
        arch = Architecture.selectBy(
                            Type=str(self.comboBoxArchitecture.currentText())
                            )
        dist = Distribution.selectBy(
                            Name=str(self.comboBoxDistribution.currentText())
                            )
        MustBe = self.listWidgetToList( self.listWidgetMustBe )
        MayNotBe = self.listWidgetToList( self.listWidgetMayNot )
        MayBe = self.listWidgetToList( self.listWidgetMay )
        try:
            templt = Template.selectBy(
                            Category=str(self.comboBoxTemplate.currentText())
                            )
            host = Host.selectBy(DnsName=hostname)
            if office[0] <> None:
                host[0].Office=office[0]
            if arch[0] <> None:
                host[0].Architecture=arch[0]
            if dist[0] <> None:
                host[0].Distribution=dist[0]
            if templt[0] <> None:
                host[0].Template=templt[0]
            if mac <> None:
                host[0].MacAddress=mac
            host[0].setPackages(MustBe, MayNotBe, MayBe)
            logModule.log("Modificado el host "+hostname)
            self.widget.close()
        except Invalid,e:
            logModule.log(e)
        except dberrors,err:
            logModule.log("Error al guardar en la base: "+str(err))
        
    def edit_view(self,host):
        self.lineEditHostname.setText(host.DnsName)
        self.lineEditHostname.setEnabled(False)
        self.pushButtonOk.setText("Modificar")
        self.pushButtonOk.sizeHint()
        self.lineEditMac.setText(host.MacAddress)
        if host.Architecture <> None:
            for i in range(0,self.comboBoxArchitecture.count()):
                if (self.comboBoxArchitecture.itemText(i) == 
                    host.Architecture.Type):
                    self.comboBoxArchitecture.setCurrentIndex(i)
        else:
            self.comboBoxArchitecture.setEditText("")

        if host.Distribution <> None:
            for i in range(0,self.comboBoxDistribution.count()):
                if (self.comboBoxDistribution.itemText(i) == 
                    host.Distribution.Name):
                    self.comboBoxDistribution.setCurrentIndex(i)
        else:
            self.comboBoxDistribution.setEditText("")

        if host.Office <> None:
            for i in range(0,self.comboBoxOffice.count()):
                if self.comboBoxOffice.itemText(i) == host.Office.Name:
                    self.comboBoxOffice.setCurrentIndex(i)
        else:
            self.comboBoxOffice.setEditText("")

        if host.Template <> None:
            for i in range(0,self.comboBoxTemplate.count()):
                if self.comboBoxTemplate.itemText(i) == host.Template.Category:
                    self.comboBoxTemplate.setCurrentIndex(i)
        else:
            #FIXME: cuando se borra el template asociado, en el modo edicion toma el siguiente, lo que esta mal. Deberia mostrar None o nada.
            self.comboBoxTemplate.setEditText("None")

        must_have = HostPackageMustHave.selectBy(host=host.id)
        may_have = HostPackageMayHave.selectBy(host=host.id)
        may_not_have = HostPackageMayNotHave.selectBy(host=host.id)
        self.loadPackagesOnWidget(must_have,self.listWidgetMustBe)
        self.loadPackagesOnWidget(may_have,self.listWidgetMay)
        self.loadPackagesOnWidget(may_not_have,self.listWidgetMayNot)
      
    def loadPackagesOnWidget(self, listPackages, widget):
        widget.clear()
        for pack in listPackages:
            widget.addItem(str(pack.packageID))


    def loadwidgetFromTemplate(self):
        template = Template.selectBy( 
                            Category=str(self.comboBoxTemplate.currentText()) 
                            )
        self.loadPackageWidgetFromTemplate( template[0], self.listWidgetMustBe,
                                    self.listWidgetMayNot,self.listWidgetMay )

    def listWidgetToList(self,listWidget):
        list = []
        for i in range(listWidget.count()):
            list.append(str(listWidget.item(i).text()))
        return list
                                        
    def add_host(self):
        hostname = str(self.lineEditHostname.text())
        mac = str(self.lineEditMac.text())
        office = Office.selectBy(Name=str(self.comboBoxOffice.currentText()))
        arch = Architecture.selectBy(
                            Type=str(self.comboBoxArchitecture.currentText())
                            )
        dist = Distribution.selectBy(
                            Name=str(self.comboBoxDistribution.currentText())
                            )
        MustBe = self.listWidgetToList( self.listWidgetMustBe )
        MayNotBe = self.listWidgetToList( self.listWidgetMayNot )
        MayBe = self.listWidgetToList( self.listWidgetMay )
        try:
            templt = Template.selectBy(
                              Category=str(self.comboBoxTemplate.currentText())
                              )
            new_host = Host(MacAddress=mac, DnsName=hostname, Office=office[0],
                                Architecture=arch[0], Distribution=dist[0], 
                                Template=templt[0])   
            new_host.setPackages(MustBe, MayNotBe, MayBe)
            logModule.log("Agregado el host "+hostname)
            self.widget.close()
        except Invalid,e:
            logModule.log(e)
        except dberrors.DuplicateEntryError,err:
            logModule.log("El Host ya existe. Error: "+str(err))

    def loadPackageListOnWidget(self, list, listwidget):
        listwidget.clear()
        for package in list:
            listwidget.addItem(str(package))

    def loadPackageWidgetFromTemplate(self, template, must_have, may_have, 
                                      may_not_have):
        self.loadPackageListOnWidget(template.PackagesMustHave(), must_have)
        self.loadPackageListOnWidget(template.PackagesMayHave(), may_have)
        self.loadPackageListOnWidget( template.PackagesMayNotHave(), 
                                      may_not_have)

    def Refresh_Architectures(self):
        architectures=Architecture.select()
        for architecture in architectures:
            self.comboBoxArchitecture.addItem( architecture.Type )

    def Refresh_Distributions(self):
        distributions=Distribution.select()
        for distribution in distributions:
            self.comboBoxDistribution.addItem( distribution.Name )
    
    def Refresh_Offices(self):
        offices=Office.select()
        for office in offices:
            self.comboBoxOffice.addItem( office.Name )

    def Refresh_Templates(self):
        templates=Template.select()
        for template in templates:
            self.comboBoxTemplate.addItem( template.Category )

    def Tab_change(self):
        item_selected = self.tabWidgetAddHost.currentIndex()
        if item_selected == 1:
            if not self.editMode:
                self.loadwidgetFromTemplate()
            if  self.listWidgetMustBeAvaible.count()==0:
                self.load_package_avaible()

    def loadPackagesAvaibleOnWidget(self,packages,widgetAvaible,widgetBe):
        widgetAvaible.reset()
        for package in packages:
            if not list(widgetBe.findItems(package,QtCore.Qt.MatchExactly)):
                widgetAvaible.addItem(package)

    def load_package_avaible(self):
        self.__class__.message = QtGui.QProgressDialog(
                       "cargando informacion de paquetes","Cancelar",0,4
                       )
        self.__class__.message.setWindowModality(QtCore.Qt.WindowModal)
        self.__class__.message.forceShow()
        self.__class__.message.setValue(0)
        time.sleep(0.1)
        allPackages=packages().getDbPackagesList('order')
        self.__class__.message.setValue(1)
        time.sleep(0.1)
        self.loadPackagesAvaibleOnWidget(allPackages,
                                        self.listWidgetMustBeAvaible, 
                                        self.listWidgetMustBe)
        self.__class__.message.setValue(2)
        time.sleep(0.1)
        self.loadPackagesAvaibleOnWidget(allPackages,
                                        self.listWidgetMayNotAvaible, 
                                        self.listWidgetMayNot)
        self.__class__.message.setValue(3)
        time.sleep(0.1)
        self.loadPackagesAvaibleOnWidget(allPackages,
                                        self.listWidgetMayAvaible, 
                                        self.listWidgetMay)
        self.__class__.message.setValue(4)
        del(self.__class__.message)

    def list_widget_swap(self,origin,destiny):
        selection = origin.selectedItems()
        for item in selection:
            #FIXME: hay que hacer que borre los items en avaible que ya estan
            destiny.addItem(item.text())
            origin.takeItem(origin.row(item))

    def MustBeAdd(self):      
        self.list_widget_swap(
                self.listWidgetMustBeAvaible,self.listWidgetMustBe
                )

    def MayNotBeAdd(self):
        self.list_widget_swap(
                self.listWidgetMayNotAvaible,self.listWidgetMayNot
                )

    def MayBeAdd(self):
        self.list_widget_swap(
                self.listWidgetMayAvaible,self.listWidgetMay
                )

    def MustBeRemove(self):       
        self.list_widget_swap(
                self.listWidgetMustBe,self.listWidgetMustBeAvaible
                )

    def MayNotBeRemove(self):
        self.list_widget_swap(
                self.listWidgetMayNot,self.listWidgetMayNotAvaible
                )

    def MayBeRemove(self):
        self.list_widget_swap(
                self.listWidgetMay,self.listWidgetMayAvaible
                )

    def listWidgetToList(self,listWidget):
        list = []
        for i in range(listWidget.count()):
            list.append( str( listWidget.item(i).text() ) )
        return list

    def deleteHost(self, hostname):
        host_to_delete = Host.selectBy(DnsName=hostname)
        host_to_delete[0].destroySelf()
        self.deleteFiles(hostname)

    def deleteFiles(self,hostname):
        config=configuration()
        pkgsync_path=config.PkgsyncPath+'/'
        del(config)
        import os
        logModule.log("Eliminando "+pkgsync_path+hostname+'.MustHave')
        os.remove(pkgsync_path+hostname+'.MustHave')
        logModule.log("Eliminando "+pkgsync_path+hostname+'.MayHave')
        os.remove(pkgsync_path+hostname+'.MayHave')
        logModule.log("Eliminando "+pkgsync_path+hostname+'.MayNotHave')
        os.remove(pkgsync_path+hostname+'.MayNotHave')
        logModule.log("Eliminando "+pkgsync_path+hostname+'.aptRelease')
        os.remove(pkgsync_path+hostname+'.aptRelease')
